/*-------------------------------------------------------------------------
 *
 * ts_public.h
 *	  各种 Tsearch 模块（如解析器和字典）的公共接口.
 *
 * Copyright (c) 1998-2022, PostgreSQL Global Development Group
 *
 * src/include/tsearch/ts_public.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef _PG_TS_PUBLIC_H_
#define _PG_TS_PUBLIC_H_

#include "tsearch/ts_type.h"

/*
 * 解析器框架
 */

/*
 * 解析器 prslextype 方法的返回类型
 */
typedef struct
{
	int			lexid;
	char	   *alias;
	char	   *descr;
} LexDescr;

/*
 * 与标题生成器的接口 (tsparser 的 prsheadline 函数)
 *
 * HeadlineParsedText 描述要高亮显示的文本。
 * 一些字段从核心代码传递到 prsheadline 函数，
 * 而其他字段则从 prsheadline 函数输出。
 *
 * 主要数据是 words[]，一个 HeadlineWordEntry 数组，
 * 每个 token 一个条目，长度为 curwords。
 * HeadlineWordEntry 的字段如下：
 *
 * in, selected, replace, skip: 这些标志最初为零
 * 可由 prsheadline 函数设置。标记为“in”的一组连续 token
 * 形成一个要输出的“片段”。
 * 此类 token 还可以标记为 selected、replace 或 skip
 * 以修改它们的显示方式。 (如果您设置了多个这些
 * 位，则会得到一个未指定的行为。)
 *
 * type, len, pos, word: 由核心代码填充以描述 token。
 *
 * item: 如果 token 匹配任何感兴趣的 tsquery 的操作数，
 * 则指向该操作数的指针。 (如果有多个匹配的
 * 操作数，我们会生成额外的 HeadlineWordEntry 副本来保存
 * 所有指针。额外的条目通过 repeated = 1 标记，
 * 除非检查项指针，否则应被忽略。)
 */
typedef struct
{
	uint32		selected:1,		/* 该 token 需要被高亮 */
				in:1,			/* 该 token 是标题的一部分 */
				replace:1,		/* 该 token 将被替换为空格 */
				repeated:1,		/* 重复条目以保存项指针 */
				skip:1,			/* 该 token 将被跳过（不输出） */
				unused:3,		/* 可用位 */
				type:8,			/* 解析器的 token 类别 */
				len:16;			/* token 的长度 */
	WordEntryPos pos;			/* token 的位置 */
	char	   *word;			/* token 的文本（非空终止） */
	QueryOperand *item;			/* 匹配的查询操作数，若无则为 NULL */
} HeadlineWordEntry;

typedef struct
{
	/* 核心代码在调用prsheadline函数之前填写的字段: */
	HeadlineWordEntry *words;
	int32		lenwords;		/* words[]的分配长度 */
	int32		curwords;		/* 当前有效条目的数量 */
	int32		vectorpos;		/* 由 ts_parse.c 在填充 pos 字段时使用 */

	/* prsheadline 函数必须填充这些字段： */
	/* 用于标记选定 token 和分隔片段的字符串： */
	char	   *startsel;		/* palloc 的字符串 */
	char	   *stopsel;
	char	   *fragdelim;
	int16		startsellen;	/* 字符串的长度 */
	int16		stopsellen;
	int16		fragdelimlen;
} HeadlineParsedText;

/*
 * tsearch 子系统的常用有用内容
 */
extern char *get_tsearch_config_filename(const char *basename,
										 const char *extension);

/*
 * 常用的停用词列表管理
 */
typedef struct
{
	int			len;
	char	  **stop;
} StopList;

extern void readstoplist(const char *fname, StopList *s,
						 char *(*wordop) (const char *));
extern bool searchstoplist(StopList *s, char *key);

/*
 * 与字典的接口
 */

/* 任何 lexize 函数的返回结构 */
typedef struct
{
	/*----------
	 * 当前分割词的变体数量。例如，挪威语
	 * 单词 'fotballklubber' 有两个变体可以分割：( fotball, klubb )
	 * 和 ( fot, ball, klubb )。因此，字典应返回：
	 *
	 * nvariant    lexeme
	 *	   1	   fotball
	 *	   1	   klubb
	 *	   2	   fot
	 *	   2	   ball
	 *	   2	   klubb
	 *
	 * 一般来说，如果 TSLexeme 的 nvariant 值与前一个相同，
	 * 则会被视为属于同一分割变体。
	 * 精确值并不重要，重要的是从一个 lexeme 到下一个的变化。
	 *----------
	 */
	uint16		nvariant;

	uint16		flags;			/* 请参见下面的标志位 */

	char	   *lexeme;			/* C string */
} TSLexeme;

/* 可以出现在 TSLexeme.flags 中的标志位 */
#define TSL_ADDPOS		0x01
#define TSL_PREFIX		0x02
#define TSL_FILTER		0x04

/*
 * 支持复杂字典（如同义词词典）的结构体。
 * dictlexize 方法的第 4 个参数是指向此的指针
 */
typedef struct
{
	bool		isend;			/* 输入：关于文本结束的 lexize_info 的标记已
								 * 达到 */
	bool		getnext;		/* 输出：字典想要下一个词素 */
	void	   *private_state;	/* 在调用之间的内部字典状态
								 * getnext == true */
} DictSubState;

#endif							/* _PG_TS_PUBLIC_H_ */
